home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / unix-emulation-src / unix-entry.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-30  |  17.3 KB  |  705 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1993, 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. #if defined(THINK_C)
  12. #include <MacHeaders>
  13. #else
  14. #include <Types.h>
  15. #include <Memory.h>
  16. #include <Quickdraw.h>
  17. #include <Windows.h>
  18. #include <TextEdit.h>
  19. #include <Errors.h>
  20. #include <LowMem.h>
  21. #include <Resources.h>
  22. #endif
  23.  
  24. #include <Processes.h>
  25. #include "errno.h"
  26. #include "stdio.h"
  27. #include "sys/dir.h"
  28. #include "sys/ioctl.h"
  29. #include "unix-types.h"
  30. #include "unix-constants.h"
  31.  
  32. #define PIPEBUFSIZE            1024
  33.  
  34. struct unix_object **object_list;
  35.  
  36. static char *
  37. getenv_internal(char *target)
  38. {
  39.     char ***p,**e,*s,t[256],*strchr();
  40.     int len;
  41.  
  42.     p = proctable[current_process_index].environ_address;
  43.     if (p == 0L || *p == 0L) return 0L;
  44.  
  45.     for (e = *p; *e != 0L; ++e) {
  46.         s = strchr(*e,'=');
  47.         if (!s) continue;
  48.         len = s - *e;
  49.         if (len >= sizeof(t)) continue;
  50.         memcpy(t,*e,len);
  51.         t[len] = '\0';
  52.         if (!strcmp(t,target)) return s+1;
  53.     }
  54.     
  55.     return 0L;
  56. }
  57.  
  58. void
  59. set_errno(int err)
  60. {
  61.     struct proc *p = &proctable[current_process_index];
  62.     
  63.     if (p->errno_address == 0L) return;
  64.     
  65.     if (err > 0)
  66.         *p->errno_address = err;
  67.     else {
  68.         switch (err) {
  69.         case noErr:        *p->errno_address = 0;        break;
  70.         case eofErr:    *p->errno_address = EEOF;    break;
  71.         case dirNFErr:
  72.         case nsvErr:    *p->errno_address = ENOTDIR;break;
  73.         case bdNamErr:
  74.         case fnfErr:    *p->errno_address = ENOENT;    break;
  75.         case permErr:    *p->errno_address = EPERM;    break;
  76.         default:        *p->errno_address = EUNDOC;    break;
  77.         }
  78.     }
  79. }
  80.  
  81. char *
  82. getwd_internal(char *u)
  83. {
  84.     char *s = proctable[current_process_index].cwd_string;
  85.     if (s == 0L || strlen(s) >= MAXPATHLEN)
  86.         return 0L;
  87.     else {
  88.         strcpy(u,s);
  89.         return u;
  90.     }
  91. }
  92.  
  93. struct unix_object **
  94. add_object(long flavor,long translate)
  95. {
  96.     int err;
  97.     struct unix_object **object;
  98.     
  99.     object = (struct unix_object **)NewHandle(sizeof(struct unix_object));
  100.     err = MemError();
  101.     if (err) return 0L;
  102.     
  103.     (**object).prev = 0L;
  104.     (**object).next = object_list;
  105.     if (object_list != 0L)
  106.         (**object_list).prev = object;
  107.     object_list = object;
  108.     (**object).flavor = flavor;
  109.     (**object).translate = translate;
  110.     (**object).count = 1;
  111.     return object;
  112. }
  113.  
  114. static void
  115. remove_object(struct unix_object **object)
  116. {
  117.     if (object_list == object)
  118.         object_list = (**object).next;
  119.     if ((**object).prev != 0L)
  120.         (**(**object).prev).next = (**object).next;
  121.     if ((**object).next != 0L)
  122.         (**(**object).next).prev = (**object).prev;
  123.     DisposHandle((Handle)object);
  124. }
  125.  
  126. int
  127. dec_object_count(struct unix_object **object)
  128. {
  129.     int count = --(**object).count;
  130.     if (count == 0) remove_object(object);
  131.     return count;
  132. }
  133.  
  134. struct unix_object **
  135. lookup_object(long flavor,long data)
  136. {
  137.     struct unix_object **object;
  138.     
  139.     for (object = object_list; object != 0L; object = (**object).next) {
  140.         if ((**object).flavor == flavor) {
  141.             switch (flavor) {
  142.             case object_flavor_file:
  143.                 if (!bcmp((void *)data,&(**object).u.file.spec,sizeof(FSSpec)))
  144.                     return object;
  145.                 break;
  146.             case object_flavor_pipe:
  147.                 if (data == (**object).u.pipe.pipeNum)
  148.                     return object;
  149.                 break;
  150.             default:
  151.                 return object;
  152.             }
  153.         }
  154.     }
  155.     
  156.     return 0L;
  157. }
  158.  
  159. void
  160. add_given_fd(int index,int fd,long flavor,
  161.     long (*dispatch)(long,long,long,char *,long,struct savearea_lomem *),
  162.     struct unix_object **object)
  163. {
  164.     struct proc *p = &proctable[index];
  165.     p->fd[fd].flavor = flavor;
  166.     p->fd[fd].object = object;
  167.     p->fd[fd].dispatch = dispatch;
  168. }
  169.  
  170. long
  171. add_fd(long flavor,long (*dispatch)(long,long,long,char *,long,struct savearea_lomem *),struct unix_object **object)
  172. {
  173.     int i;
  174.     for (i = 0; i<MAXDESC; ++i)
  175.         if (proctable[current_process_index].fd[i].flavor == fd_flavor_unused) {
  176.             add_given_fd(current_process_index,i,flavor,dispatch,object);
  177.             return i;
  178.         }
  179.     
  180.     return -1;
  181. }
  182.  
  183. static int
  184. only_we_own_object(struct unix_object **object)
  185. {
  186.     int i,j;
  187.     
  188.     for (i = 0; i<MAXPROC; ++i) {
  189.         if (i == current_process_index) continue;
  190.         if (proctable[i].pid == 0) continue;
  191.         for (j = 0; j<MAXDESC; ++j)
  192.             if (proctable[i].fd[j].flavor != fd_flavor_unused &&
  193.                     proctable[i].fd[j].object == object)
  194.                 return 0;
  195.     }
  196.     
  197.     return 1;
  198. }
  199.  
  200. static long
  201. pipe_dispatch(long task,long index,long fd,char *p,long n,struct savearea_lomem *lomem)
  202. {
  203.     int i,taken,nleft,avail;
  204.     int m,nwritten;
  205.     struct unix_object **object;
  206.     
  207.     object = proctable[index].fd[fd].object;
  208.     
  209.     switch (task) {
  210.     case unix_read:
  211.         while (1) {
  212.             taken = ((**object).u.pipe.wp + PIPEBUFSIZE - (**object).u.pipe.rp) & (PIPEBUFSIZE-1);
  213.             avail = PIPEBUFSIZE-1 - taken;
  214.             if (taken > 0) break;
  215.             if (only_we_own_object(object))
  216.                 return 0; /* No one else can write, so EOF. */
  217.             else {
  218. //printnum("$$$ Nothing to read, letting someone else write",index);
  219.                 run_another_process(); /* Let someone write */
  220. //printnum("$$$ Reading again",index);
  221.             }
  222.         }
  223.         
  224.         if (n > taken) n = taken;
  225.         for (i = 0; i<n; ++i) {
  226.             *p++ = (**object).u.pipe.pipeBuf[(**object).u.pipe.rp];
  227.             (**object).u.pipe.rp = ((**object).u.pipe.rp + 1) & (PIPEBUFSIZE-1);
  228.         }
  229.         return n;
  230.     case unix_write:
  231.         nleft = n;
  232.         nwritten = 0;
  233.         
  234.         while (1) {
  235.             if (nleft == 0) return nwritten;
  236.             /* This is not the right test, we need to keep a count of
  237.                readers and writers. */
  238.             if (only_we_own_object(object)) {
  239.                 raise_internal(SIGPIPE,lomem);
  240.                 return nwritten;
  241.             }
  242.             taken = ((**object).u.pipe.wp + PIPEBUFSIZE - (**object).u.pipe.rp) & (PIPEBUFSIZE-1);
  243.             avail = PIPEBUFSIZE-1 - taken;
  244.             if (avail == 0) {
  245.                 /* Let someone read */
  246. //printnum("### No room to write, letting someone else read",index);
  247.                 run_another_process();
  248. //printnum("### Writing again",index);
  249.                 continue;
  250.             }
  251.  
  252.             m = nleft;
  253.             if (m > avail) m = avail;
  254.             for (i = 0; i<m; ++i) {
  255.                 (**object).u.pipe.pipeBuf[(**object).u.pipe.wp] = *p++;
  256.                 (**object).u.pipe.wp = ((**object).u.pipe.wp + 1) & (PIPEBUFSIZE-1);
  257.                 ++nwritten;
  258.                 --nleft;
  259.             }
  260.         }
  261.     case unix_close:
  262.         if ((**object).u.pipe.pipeBuf != 0L)
  263.             DisposPtr((**object).u.pipe.pipeBuf);
  264.         return 0;
  265.     case unix_fionread:
  266.         *(int *)p = ((**object).u.pipe.wp + PIPEBUFSIZE - (**object).u.pipe.rp) & (PIPEBUFSIZE-1);
  267.         return 0;
  268.     }
  269. }
  270.  
  271. void
  272. kernel_entry(struct savearea_lomem *lomem)
  273. {
  274.     if (lomem == 0L) return;
  275.  
  276.     GetPort(&lomem->port);
  277.     lomem->zone = GetZone();
  278.     lomem->curResFile = CurResFile();
  279.     lomem->ApplLimit = LMGetApplLimit();
  280.     lomem->HeapEnd = LMGetHeapEnd();
  281.     lomem->HiHeapMark = LMHiHeapMark;
  282.  
  283.     SetZone(ApplicZone());
  284. }
  285.  
  286. void
  287. kernel_exit(struct savearea_lomem *lomem)
  288. {
  289.     if (lomem == 0L) return;
  290.  
  291.     SetZone(lomem->zone);
  292.     UseResFile(lomem->curResFile);
  293.     SetPort(lomem->port);
  294.     LMSetApplLimit(lomem->ApplLimit);
  295.     LMSetHeapEnd(lomem->HeapEnd);
  296.     LMHiHeapMark = lomem->HiHeapMark;
  297. }
  298.  
  299. static int unix_entry1(int,struct savearea_lomem *,va_list);
  300. static int ioctl_internal(int,int,int *,struct savearea_lomem *);
  301. static int isatty_internal(int);
  302.  
  303. int
  304. unix_entry(int dispatch_code,int *errno_address,va_list arglist)
  305. {
  306.     int i,result,in_front;
  307.     int now = TickCount();
  308.     struct proc *p = &proctable[current_process_index],*q;
  309.     struct savearea_lomem lomem;
  310.     extern char got_interrupt_from_terminal;
  311.     extern int Vquit_in_main_event_loop;
  312.  
  313.     p->errno_address = errno_address;
  314.  
  315.     kernel_entry(&lomem);
  316.  
  317.     /* Pretend we have a multitasking operating system. */
  318.     read_events(1);
  319.     if (p->start_time + 60 <= now) run_another_process();
  320.  
  321.     /* Do the requested operation. */
  322.     result = unix_entry1(dispatch_code,&lomem,arglist);
  323.  
  324.     /* Look for interrupts. */
  325.     for (i = 0, q = proctable; i<MAXPROC; ++i, ++q) {
  326.         if (q->pid != 0 && q->alarm_time != 0 && q->alarm_time <= now) {
  327.             q->alarm_time = 0;
  328.             kill_internal(q->pid,SIGALRM,&lomem);
  329.         }
  330.     }
  331.     if (got_interrupt_from_terminal) {
  332.         /* One day we'll do something reasonable with process groups. */
  333.         got_interrupt_from_terminal = 0;
  334.         kill_internal(proctable[0].pid,SIGINT,&lomem);
  335.     }
  336.     if (Vquit_in_main_event_loop) {
  337.         Vquit_in_main_event_loop = 0;
  338.         kill_internal(1,SIGKILL,&lomem);
  339.     }
  340.     
  341.     kernel_exit(&lomem);
  342.  
  343.     return result;
  344. }
  345.  
  346. static int
  347. unix_entry1(int dispatch_code,struct savearea_lomem *lomem,va_list arglist)
  348. {
  349.     int err,fd,i,j,k,mode;
  350.     char *s,*t;
  351.     struct unix_object **object;
  352.  
  353.     switch (dispatch_code) {
  354.     case unix_open:
  355.         s = va_arg(arglist,char *);
  356.         i = va_arg(arglist,int);
  357.         return open_internal(s,i);
  358.     case unix_creat:
  359.         s = va_arg(arglist,char *);
  360.         i = va_arg(arglist,int);
  361.         return creat_internal(s,i);
  362.     case unix_dup:
  363.         i = va_arg(arglist,int);
  364.         return dup_internal(i);
  365.     case unix_dup2:
  366.         i = va_arg(arglist,int);
  367.         j = va_arg(arglist,int);
  368.         if (proctable[current_process_index].fd[j].flavor != fd_flavor_unused) {
  369.             err = close_internal(current_process_index,j,lomem);
  370.             if (err == -1) return -1;
  371.         }
  372.  
  373.         add_given_fd(current_process_index,j,
  374.                      proctable[current_process_index].fd[i].flavor,
  375.                      proctable[current_process_index].fd[i].dispatch,
  376.                      proctable[current_process_index].fd[i].object);
  377.         ++(**proctable[current_process_index].fd[i].object).count;
  378.         return j;
  379.     case unix_read:
  380.     case unix_write:
  381.         i = va_arg(arglist,int);
  382.         s = va_arg(arglist,char *);
  383.         j = va_arg(arglist,int);
  384.         return read_write_internal(dispatch_code,i,s,j,lomem);
  385.     case unix_close:
  386.         i = va_arg(arglist,int);
  387.         return close_internal(current_process_index,i,lomem);
  388.     case unix_lseek:
  389.         i = va_arg(arglist,int);
  390.         j = va_arg(arglist,int);
  391.         k = va_arg(arglist,int);
  392.         
  393.         switch (k) {
  394.         case 0: mode = fsFromStart;    break;
  395.         case 1: mode = fsFromMark;    break;
  396.         case 2: mode = fsFromLEOF;    break;
  397.         default: return -1;
  398.         }
  399.         err = SetFPos((**proctable[current_process_index].fd[i].object).u.file.refNum,mode,j);
  400.         if (err) return -1;
  401.         err = GetFPos((**proctable[current_process_index].fd[i].object).u.file.refNum,(long *)&j);
  402.         if (err) return -1;
  403.         return j;
  404.     case unix_unlink:
  405.         s = va_arg(arglist,char *);
  406.         return unlink_internal(s);
  407.     case unix_pipe:
  408.     {
  409.         int *fd = va_arg(arglist,int *);
  410.         static int pipeNum = 0;
  411.         void *t;
  412.         
  413.         /* fd[0] is for reading */
  414.         /* fd[1] is for writing */
  415.         
  416.         fd[0] = add_fd(fd_flavor_pipe,pipe_dispatch,0L);
  417.         if (fd[0] == -1) return -1;
  418.         fd[1] = add_fd(fd_flavor_pipe,pipe_dispatch,0L);
  419.         if (fd[1] == -1) { proctable[current_process_index].fd[fd[0]].flavor = fd_flavor_unused; return -1; }
  420.         
  421.         object = add_object(object_flavor_pipe,0);
  422.         if (object == 0L) return -1;
  423.         (**object).u.pipe.pipeNum = pipeNum++;
  424.         t = NewPtr(PIPEBUFSIZE);
  425.         (**object).u.pipe.pipeBuf = t;
  426.         (**object).u.pipe.wp = (**object).u.pipe.rp = 0;
  427.         if (MemError()) { dec_object_count(object); return -1; }
  428.         ++(**object).count;
  429.         
  430.         proctable[current_process_index].fd[fd[0]].object = object;
  431.         proctable[current_process_index].fd[fd[1]].object = object;
  432.         return 0;
  433.     }
  434.     case unix_vfork1:
  435.         return vfork1_internal();
  436.     case unix_vfork2:
  437.         i = va_arg(arglist,int);
  438.         return vfork2_internal(lomem,i);
  439.     case unix_execvp:
  440.         s = va_arg(arglist,char *);
  441.         t = va_arg(arglist,char *);
  442.         return execvp_internal(s,(char **)t);
  443.     case unix__exit:
  444.         i = va_arg(arglist,int);
  445.         _exit_internal(i);
  446.         return -1; /* "Never happens" */
  447.     case unix_exit:
  448.         i = va_arg(arglist,int);
  449.         exit_internal(i);
  450.         return -1; /* "Never happens" */
  451.     case unix_signal:
  452.         i = va_arg(arglist,int);
  453.         s = va_arg(arglist,char *);
  454.         return signal_internal(i,(int (*)())s);
  455.     case unix_raise:
  456.         i = va_arg(arglist,int);
  457.         return raise_internal(i,lomem);
  458.     case unix_kill:
  459.         i = va_arg(arglist,int);
  460.         j = va_arg(arglist,int);
  461.         return kill_internal(i,j,lomem);
  462.     case unix_ioctl:
  463.         i = va_arg(arglist,int);
  464.         j = va_arg(arglist,int);
  465.         s = va_arg(arglist,char *);
  466.         return ioctl_internal(i,j,(int *)s,lomem);
  467.     case unix_wait:
  468.         s = va_arg(arglist,char *);
  469.         return wait3_internal((long *)s,0,0);
  470.     case unix_wait3:
  471.         s = va_arg(arglist,char *);
  472.         i = va_arg(arglist,int);
  473.         j = va_arg(arglist,int);
  474.         return wait3_internal((long *)s,i,j);
  475.     case unix_alarm:
  476.         i = va_arg(arglist,int);
  477.         return alarm_internal(i);
  478.     case unix_pause:
  479.         return pause_internal();
  480.     case unix_chdir:
  481.         s = va_arg(arglist,char *);
  482.         return chdir_internal(s);
  483.     case unix_getwd:
  484.         s = va_arg(arglist,char *);
  485.         return (int)getwd_internal(s);
  486.     case unix_sleep:
  487.         i = va_arg(arglist,int);
  488.         return sleep_internal(i);
  489.     case unix_getpid:
  490.         return proctable[current_process_index].pid;
  491.     case unix_getppid:
  492.         return proctable[current_process_index].ppid;
  493.     case unix_unixfn2FSSpec:
  494.         s = va_arg(arglist,char *);
  495.         t = va_arg(arglist,char *);
  496.         i = va_arg(arglist,int);
  497.         return unixfn2FSSpec_internal(s,t,i);
  498.     case unix_access:
  499.         s = va_arg(arglist,char *);
  500.         i = va_arg(arglist,int);
  501.         return access_internal(s,i);
  502.     case unix_rename:
  503.         s = va_arg(arglist,char *);
  504.         t = va_arg(arglist,char *);
  505.         return rename_internal(s,t);
  506.     case unix_chmod:
  507.         s = va_arg(arglist,char *);
  508.         i = va_arg(arglist,int);
  509.         return chmod_internal(s,i);
  510.     case unix_chgrp:
  511.         s = va_arg(arglist,char *);
  512.         i = va_arg(arglist,int);
  513.         return chgrp_internal(s,i);
  514.     case unix_chown:
  515.         s = va_arg(arglist,char *);
  516.         i = va_arg(arglist,int);
  517.         return chown_internal(s,i);
  518.     case unix_stat:
  519.         s = va_arg(arglist,char *);
  520.         t = va_arg(arglist,char *);
  521.         return stat_internal(s,(struct stat *)t,0);
  522.     case unix_lstat:
  523.         s = va_arg(arglist,char *);
  524.         t = va_arg(arglist,char *);
  525.         return stat_internal(s,(struct stat *)t,1);
  526.     case unix_stat_spec:
  527.         s = va_arg(arglist,char *);
  528.         s = va_arg(arglist,char *);
  529.         i = va_arg(arglist,int);
  530.         return stat_spec_internal((FSSpec *)s,(struct stat *)t,i);
  531.     case unix_isatty:
  532.         i = va_arg(arglist,int);
  533.         return isatty_internal(i);
  534.     case unix_opendir:
  535.         s = va_arg(arglist,char *);
  536.         return opendir_internal(s);
  537.     case unix_readdir:
  538.         s = va_arg(arglist,char *);
  539.         return readdir_internal((DIR *)s);
  540.     case unix_closedir:
  541.         s = va_arg(arglist,char *);
  542.         return closedir_internal((DIR *)s);
  543.     case unix_getenv:
  544.         s = va_arg(arglist,char *);
  545.         return (int)getenv_internal(s);
  546.     case unix_readlink:
  547.         s = va_arg(arglist,char *);
  548.         t = va_arg(arglist,char *);
  549.         i = va_arg(arglist,int);
  550.         return readlink_internal(s,t,i);
  551.     case unix_FSSpec2unixfn:
  552.         s = va_arg(arglist,char *);
  553.         t = va_arg(arglist,char *);
  554.         return FSSpec2unixfn_internal((FSSpec *)s,(Handle *)t);
  555.     case unix_symlink:
  556.         s = va_arg(arglist,char *);
  557.         t = va_arg(arglist,char *);
  558.         return symlink_internal(s,t);
  559.     case unix__iob:
  560.         i = va_arg(arglist,int);
  561.         return (int)&proctable[current_process_index].iob[i];
  562.     case unix_fflush:
  563.         s = va_arg(arglist,char *);
  564.         return fflush_internal((FILE *)s,lomem);
  565.     case unix_fclose:
  566.         s = va_arg(arglist,char *);
  567.         fclose_internal((FILE *)s,lomem);
  568.         return 0;
  569.     case unix_mkdir:
  570.         s = va_arg(arglist,char *);
  571.         i = va_arg(arglist,int);
  572.         return mkdir_internal(s,i);
  573.     case unix_rmdir:
  574.         s = va_arg(arglist,char *);
  575.         return rmdir_internal(s);
  576.     case unix_utime:
  577.         s = va_arg(arglist,char *);
  578.         t = va_arg(arglist,char *);
  579.         return utime_internal(s,(struct utimbuf *)t);
  580.     case unix_unix_nop:
  581.         return 0;
  582.     }
  583. }
  584.  
  585. void
  586. unix_translate(register char *p,register int n)
  587. {
  588.     register char c;
  589.     
  590.     while (--n >= 0) {
  591.         c = *p;
  592.         if (c == '\015')
  593.             *p = '\012';
  594.         else if (c == '\012')
  595.             *p = '\015';
  596.         ++p;
  597.     }
  598. }
  599.  
  600. long
  601. close_internal(long index,long fd,struct savearea_lomem *lomem)
  602. {
  603.     int result,count;
  604.     struct unix_object **object;
  605.     
  606.     if (proctable[index].fd[fd].flavor == fd_flavor_unused) return 0;
  607.     object = proctable[index].fd[fd].object;
  608.     count = (**object).count;
  609.     if (count == 1)
  610.         result = (*proctable[index].fd[fd].dispatch)(unix_close,index,fd,0,0,lomem);
  611.     else
  612.         result = 0;
  613.     dec_object_count(object);
  614.     proctable[index].fd[fd].flavor = fd_flavor_unused;
  615.     return result;
  616. }
  617.  
  618. long
  619. close_all_internal(long index)
  620. {
  621.     int i;
  622.     
  623.     for (i = 0; i<MAXDESC; ++i)
  624.         close_internal(index,i,0L);
  625.     return 0;
  626. }
  627.  
  628. int
  629. chdir_internal(char *s)
  630. {
  631.     Handle t;
  632.     FSSpec spec;
  633.     int err,len,at_root;
  634.     struct proc *p = &proctable[current_process_index];
  635.     
  636.     err = unixfn2FSSpec_internal(s,&spec,0);
  637.     if (err == nsDrvErr)
  638.         at_root = 1;
  639.     else {
  640.         if (err) { set_errno(err); return -1; }
  641.         at_root = 0;
  642.         err = FSSpec2unixfn_internal(&spec,&t);
  643.         if (err) { set_errno(err); return -1; }
  644.     }
  645.  
  646.     if (p->cwd_string) {
  647.         DisposPtr(p->cwd_string);
  648.         p->cwd_string = 0L;
  649.     }
  650.     HLock(t);
  651.     p->cwd_string = NewPtr((at_root ? 2 : strlen(*t)) + 1);
  652.     err = MemError();
  653.     HUnlock(t);
  654.     if (err) { set_errno(err); return -1; }
  655.     HLock(t);
  656.     strcpy(p->cwd_string,at_root ? "/" : *t);
  657.     HUnlock(t);
  658.     if (!at_root) DisposHandle(t);
  659.     return 0;
  660. }
  661.  
  662. static int
  663. ioctl_internal(int fd,int job,int *data,struct savearea_lomem *lomem)
  664. {
  665.     if (job != FIONREAD) { set_errno(EINVAL); return -1; }
  666.     if (proctable[current_process_index].fd[fd].flavor == fd_flavor_unused) { set_errno(EINVAL); return -1; }
  667.     return (*proctable[current_process_index].fd[fd].dispatch)
  668.         (unix_fionread,current_process_index,fd,(char *)data,0,lomem);
  669. }
  670.  
  671. static int
  672. isatty_internal(int fd)
  673. {
  674.     return proctable[current_process_index].fd[fd].flavor == fd_flavor_dev_tty;
  675. }
  676.  
  677. int
  678. dup_internal(int fd)
  679. {
  680.     long new_fd;
  681.     new_fd = add_fd(proctable[current_process_index].fd[fd].flavor,
  682.                     proctable[current_process_index].fd[fd].dispatch,
  683.                     proctable[current_process_index].fd[fd].object);
  684.     if (new_fd == -1) return -1;
  685.     ++(**proctable[current_process_index].fd[fd].object).count;
  686.     return new_fd;
  687. }
  688.  
  689. long
  690. read_write_internal(long dispatch_code,long fd,char *p,long n,struct savearea_lomem *lomem)
  691. {
  692.     int result;
  693.  
  694.     if ((**proctable[current_process_index].fd[fd].object).translate && dispatch_code == unix_write)
  695.         unix_translate(p,n);
  696.  
  697.     result = (*proctable[current_process_index].fd[fd].dispatch)
  698.         (dispatch_code,current_process_index,fd,p,n,lomem);
  699.  
  700.     if ((**proctable[current_process_index].fd[fd].object).translate)
  701.         unix_translate(p,result);
  702.  
  703.     return result;
  704. }
  705.